#include <windows.h>

#include <iostream>
#include <opencv2/opencv.hpp>
#include <string>
#include <vector>

using namespace cv;
using namespace std;

string files[] = {
    "zd1.png", "zd2.png", "zd3.png", "jd2.png", "jd3.png", "fz2.png", "fz3.png",
};

int time_wait = 0;
bool debuging = true;

void my_exit(int code = 0, string message = "") {
  cout << "Will exit with code " << code;
  if (message.length() > 0) {
    cout << ", message: " << message;
  }
  cout << "." << endl;
  if (debuging) Sleep(100);
  exit(code);
}

void wait_exit(int time = time_wait, int key_exit = 27) {
  int key = waitKey(time);
  if (key == key_exit) my_exit();
}

Size src_size;
int size_n = 4;
Size window_offset = Size(80, 40);
void window_grid(string window_name, int x, int y) {
  moveWindow(window_name, window_offset.width + src_size.width * x / size_n,
             window_offset.height + src_size.height * y / size_n);
}

Size max_size = Size(1024, 1024);
void resize_max_size(Mat &im, Size max_size) {
  Size size_src = im.size();
  Size size_dst = max_size;
  // 给的最大size比原来的size宽 -> 限制图像高度
  if (max_size.width / max_size.height >= size_src.width / size_src.height)
    size_dst.height = max_size.height * size_src.height / size_src.width;
  else  // 限制图像宽度
    size_dst.width = size_src.width * max_size.width / size_src.height;
  if (debuging) cout << "Resizing " << im.size() << " -> " << size_dst << endl;
  resize(im, im, size_dst);
}

void imshow_nx(string window_name, Mat im, int n = size_n) {
  resize(im, im, im.size() / n);
  imshow(window_name, im);
}

int main(int, char **) {
  string window_name = "bhw1";
  namedWindow(window_name);
  for (string file_name : files) {
    Mat src = imread(file_name);
    resize_max_size(src, max_size);
    src_size = src.size();

    imshow_nx(window_name, src);
    window_grid(window_name, 0, 0);

    // 基本处理

    // 降噪，中值
    medianBlur(src, src, 31);
    wait_exit(100);

    Mat hsv;
    cvtColor(src, hsv, COLOR_BGR2HSV);
    imshow_nx(window_name + "_hsv", hsv);
    window_grid(window_name + "_hsv", 1, 0);
    Mat gray;
    cvtColor(src, gray, COLOR_BGR2GRAY);
    imshow_nx(window_name + "_gray", gray);
    window_grid(window_name + "_gray", 2, 0);
    
    wait_exit(100);

    vector<Mat> hsv_channels;
    split(hsv, hsv_channels);
    imshow_nx(window_name + "_channels_色调", hsv_channels.at(0));
    window_grid(window_name + "_channels_色调", 0, 1);
    imshow_nx(window_name + "_channels_饱和度", hsv_channels.at(1));
    window_grid(window_name + "_channels_饱和度", 1, 1);
    imshow_nx(window_name + "_channels_明度", hsv_channels.at(2));
    window_grid(window_name + "_channels_明度", 2, 1);
    wait_exit();
  }
  return 0;
}
